package com.nervenets.template.service.impl;

import com.nervenets.general.enumeration.Action;
import com.nervenets.general.exception.LogicException;
import com.nervenets.general.service.impl.TreeServiceImpl;
import com.nervenets.general.web.params.Params;
import com.nervenets.general.web.params.QueryParams;
import com.nervenets.template.hibernate.dao.DictDao;
import com.nervenets.template.hibernate.domain.common.Dict;
import com.nervenets.template.service.DictService;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;

@Service
public class DictServiceImpl extends TreeServiceImpl<Dict, DictDao> implements DictService {
    @Override
    protected void before(Action action, Dict dict, Params... params) {
        super.before(action, dict, params);

        if (hasUniqueKey(dict.getId(), "code", dict.getCode())) {
            throw new LogicException("字典中编码不可重复");
        }

        if (hasUniqueKey(dict.getId(), new QueryParams<Dict>() {
            @Override
            public void generateSpecification(List<Predicate> predicates, Root<Dict> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                addEqualsPredicate(root.get("code"), dict.getCode());
                addEqualsPredicate(root.get("val"), dict.getVal());
            }
        })) {
            throw new LogicException(String.format("字典编码[%s]中不可存在重复的值", dict.getCode()));
        }

        Cache cache = cacheManager.getCache(Dict.CACHE_KEY);
        if (null != cache) {
            cache.evict(dict.getCode());
            cache.evict(dict.getParentId());
        }
    }

    @Override
    @Cacheable(value = Dict.CACHE_KEY, key = "#code", sync = true)
    public Dict findByCode(String code) {
        List<Dict> dicts = findAll(new QueryParams<Dict>() {
            @Override
            public void generateSpecification(List<Predicate> predicates, Root<Dict> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                addEqualsPredicate(root.get("code"), code);
            }
        }, 1);
        return dicts.isEmpty() ? null : dicts.get(0);
    }
}
